//<<<+++OPENSOURCE
//<<<+++OPENSOURCE_LICENSE
/**
 * @addtogroup FPDFAPI
 * @{
 */

/**
 * @file
 * @brief PDF resource classes.
 */
//<<<+++OPENSOURCE_MUST_BEGIN
#ifndef _FPDF_RESOURCE_
#define _FPDF_RESOURCE_

#ifndef _FPDF_PARSER_
#include "fpdf_parser.h"
#endif

#ifndef _FX_FONT_H_
#include "../fxge/fx_font.h"
#endif
//<<<+++OPENSOURCE_MUST_END

// Classes defined in this header file
class CPDF_Font;
class CPDF_Type1Font;
class CPDF_TrueTypeFont;
class CPDF_CIDFont;
class CPDF_Type3Font;
class CPDF_FontEncoding;
class CPDF_CMap;
class CPDF_CID2UnicodeMap;
class CPDF_ColorSpace;
class CPDF_Color;
class CPDF_Function;
class CPDF_Pattern;
class CPDF_TilingPattern;
class CPDF_ShadingPattern;
class CPDF_Image;
class CPDF_Face;
class CPDF_ToUnicodeMap;

class CFX_SubstFont;
class CFX_Font;
class CPDF_RenderContext;

// Classes referred in this file (excluding those defined in fpdf_parser.h
class CPDF_Form;
class CPDF_ImageObject;
class CFX_DIBitmap;
typedef struct FT_FaceRec_* FXFT_Face;
class CFX_CTTGSUBTable;
class CPDF_Page;

//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
#ifdef _FPDFAPI_MT_
	#define _FPDFAPI_CACHEPOINTER_
#endif
//<<<+++OPENSOURCE_END

/**
 * @name Font type IDs.
 */
/*@{*/

/** @brief Type1. */
#define PDFFONT_TYPE1			1
/** @brief Truetype. */
#define PDFFONT_TRUETYPE		2
/** @brief Type3. */
#define PDFFONT_TYPE3			3
/** @brief CID font. */
#define PDFFONT_CIDFONT			4

/*@}*/

/**
 * @name Font flags.
 */
/*@{*/

/** @brief All glyphs have the same width. */
#define PDFFONT_FIXEDPITCH		1
/** @brief Glyphs have serifs, which are short strokes drawn at an angle on the top and bottom of glyph stems. */
#define PDFFONT_SERIF			2
/** @brief Font contains glyphs outside the Adobe standard Latin character set. */
#define PDFFONT_SYMBOLIC		4
/** @brief Glyphs resemble cursive handwriting. */
#define PDFFONT_SCRIPT			8
/** @brief Font uses the Adobe standard Latin character set or a subset of it. */
#define PDFFONT_NONSYMBOLIC		32
/** @brief Glyphs have dominant vertical strokes that are slanted. */
#define PDFFONT_ITALIC			64
/** @brief Font contains no lowercase letters. */
#define PDFFONT_ALLCAP			0x10000
/** @brief Font contains both uppercase and lowercase letters. */
#define PDFFONT_SMALLCAP		0x20000
/** @brief Whether bold glyphs are painted with extra pixels even at very small text sizes. */
#define PDFFONT_FORCEBOLD		0x40000
/** @brief Additional font flag, use the weight and italic angle param to find substitute font. */
#define PDFFONT_USEEXTERNATTR	0x80000
/*@}*/

/** Get unicode from an Adobe glyph name. */
FX_WCHAR PDF_UnicodeFromAdobeName(const FX_CHAR* name);

/** Get Adobe glyph name from a unicode. */
CFX_ByteString PDF_AdobeNameFromUnicode(FX_WCHAR unicode);

/** @brief PDF font class. */
class CPDF_Font : public CFX_Object
{
public:
	/** The only way to create a CPDF_Font object from a font dictionary. 
	 * If bSearchOnly is TRUE, then the created font can ONLY be used for getting Unicode from charcode,
	 * all other CPDF_Font functions can't be supported.
	 *
	 * @param[in] pDoc				The PDF document.
	 * @param[in] pFontDict			The font dictionary.
	 */
	static CPDF_Font*		CreateFontF(CPDF_Document* pDoc, CPDF_Dictionary* pFontDict);

	/**
	 * Get the "stocked" fonts (Adobe base 14 fonts), which are always available for rendering activities.
	 * However, these fonts can't be directly referred in any document, unless the font resource is added to the document. 
	 * 
	 * List of currently supported standard fonts:\n
	 * - Courier, Courier-Bold, Courier-BoldOblique, Courier-Oblique.
	 * - Helvetica, Helvetica-Bold, Helvetica-BoldOblique, Helvetica-Oblique.
	 * - Times-Roman, Times-Bold, Times-Italic, Times-BoldItalic.
	 * - Symbol, ZapfDingbats.
	 *
	 * @param[in] fontname			The font name.
	 * @return a pdf font.
	 */
	static CPDF_Font*		GetStockFont(CPDF_Document* pDoc, FX_BSTR fontname);

	/** The destructor. */
	virtual ~CPDF_Font();

	/**
	 * @name Get font info.
	 */
	/*@{*/
	
	/** Get the font type. */
	int						GetFontType() const { return m_FontType; }
	/** Get the font type name. */
	CFX_ByteString			GetFontTypeName() const;
	/** Get the base font name. */
	const CFX_ByteString&	GetBaseFont() const { return m_BaseFont; }
	/** Get the substitute font. */
	const CFX_SubstFont*	GetSubstFont() const { return m_Font.GetSubstFont(); }
	/** Get the font flags. */
	FX_DWORD				GetFlags() const { return m_Flags; }

	/** Check whether the font is vertical writing. */
	virtual FX_BOOL			IsVertWriting()const;

	/*@}*/

	/**
	 * @name Get derived font class.
	 */
	/*@{*/

	/** Get a type1 font. */
	CPDF_Type1Font*			GetType1Font() const { return m_FontType == PDFFONT_TYPE1 ? (CPDF_Type1Font*)(void*)this : NULL; }
	/** Get a truetype font. */
	CPDF_TrueTypeFont*		GetTrueTypeFont() const { return m_FontType == PDFFONT_TRUETYPE ? (CPDF_TrueTypeFont*)(void*)this : NULL; }
	/** Get a CID font. */
	CPDF_CIDFont*			GetCIDFont() const { return (m_FontType == PDFFONT_CIDFONT) ? (CPDF_CIDFont*)(void*)this : NULL; }
	/** Get a type3 font. */
	CPDF_Type3Font*			GetType3Font() const { return (m_FontType == PDFFONT_TYPE3) ? (CPDF_Type3Font*)(void*)this : NULL; }

	/*@}*/

	/** Check whether the font is an embedded font. */
	FX_BOOL					IsEmbedded() const { return m_FontType == PDFFONT_TYPE3 || m_pFontFile != NULL; }
	/** Check whether the font is Unicode compatible. */
	virtual FX_BOOL			IsUnicodeCompatible() const { return FALSE; }

	/** Get the font stream. */
	CPDF_StreamAcc*			GetFontFile() const { return m_pFontFile; }
	/** Get the font dictionary. */
	CPDF_Dictionary*		GetFontDict() const { return m_pFontDict; }
	/** Check whether the font is a standard font. */
	FX_BOOL					IsStandardFont() const;
	/** Find embedded or substituted FT font face. */
	FXFT_Face				GetFace() const { return m_Font.GetFace(); }

	/**
	 * @name String operations. Note font may use multi-byte encoding.
	 */
	/*@{*/

	/**
	 * Get a charcode from a string at specified position.
	 *
	 * @param[in] pString		The string buffer.
	 * @param[in,out] offset	Input the zero-based position and receive the next charcode position.
	 * @return A charcode.
	 */
	virtual FX_DWORD		GetNextChar(FX_LPCSTR pString, int& offset) const { return (FX_BYTE)pString[offset++]; }
	/**
	 * Get the count of characters in a string.
	 *
	 * @param[in] pString		The string buffer.
	 * @param[in] size			The length in bytes of the string.
	 * @return the count of characters in the string.
	 */
	virtual int				CountChar(FX_LPCSTR pString, int size) const { return size; }
	/**
	 * Append a charcode to a string buffer.
	 *
	 * @param[in,out] str		Input a string buffer and append a charcode to it.
	 * @param[in] charcode		The charcode to append.
	 */
	void					AppendChar(CFX_ByteString& str, FX_DWORD charcode) const;
	/**
	 * Append a character code.
	 *
	 * @param[in,out] buf		Input a string buffer and append a single-byte charcode to it.
	 * @param[in] charcode		Input a character code.
	 * @return The number of bytes appended to the string buffer.
	 */
	virtual int				AppendChar(FX_LPSTR buf, FX_DWORD charcode) const { *buf = (FX_CHAR)charcode; return 1; }
	/**
	 * Get the number of bytes for the char code.
	 *
	 * @param[in] charcode		Input a charcode.
	 * @return The number of bytes of the charcode.
	 */
	virtual int				GetCharSize(FX_DWORD charcode) const { return 1; }

	/*@}*/

	/**
	 * @name Encoding operations.
	 */
	/*@{*/

	/**
	 * Get the glyph index for a charcode. Return -1 for unknown. For embedded font only.
	 *
	 * @param[in] charcode		Input a charcode.
	 * @return The glyph index of the charcode.
	 */
	virtual int				GlyphFromCharCode(FX_DWORD charcode, FX_BOOL *pVertGlyph = NULL) = 0;
    virtual int				GlyphFromCharCodeExt(FX_DWORD charcode) { return GlyphFromCharCode(charcode); }

	/**
	 * Get a unicode string for a charcode. Return 0 for unknown.
	 *
	 * @param[in] charcode		Input a charcode.
	 * @return The unicode string for the charcode.
	 */
	CFX_WideString			UnicodeFromCharCode(FX_DWORD charcode) const;
	/**
	 * Get a charcode from a Unicode. Return -1 for unknown.
	 *
	 * @param[in] Unicode		Input a unicode.
	 * @return The charcode for the unicode.
	 */
	FX_DWORD				CharCodeFromUnicode(FX_WCHAR Unicode) const;
    //<<<+++OPENSOURCE_BEGIN LIC==FOXIT
	/** Check whether a character is embedded. */
	FX_BOOL					IsCharEmbedded(FX_DWORD charcode);
    //<<<+++OPENSOURCE_END
    
	/** Get the character map. */
	CFX_CharMap*			GetCharMap() { return m_pCharMap; }
	/**
	 * Encode an unicode string to font string.
	 *
	 * @param[in] str		Input a unicode string.
	 * @return The encoded font string.
	 */
	CFX_ByteString			EncodeString(const CFX_WideString& str) const;
	/**
	 * Decode a font string to unicode string.
	 *
	 * @param[in] str		Input a font string.
	 * @return The decoded unicode string.
	 */
	CFX_WideString			DecodeString(const CFX_ByteString& str) const;

	/*@}*/

    //<<<+++OPENSOURCE_BEGIN LIC==FOXIT
	/**
	 * Use OCR to recognize a character and return Unicode. This function may be 
	 * called when UnicodeFromCharCode() fails to get a character.
	 *
	 * @param[in] charcode		Input a charcode.
	 * @return The recognized unicode.
	 */
	FX_WCHAR				RecognizeChar(FX_DWORD charcode);
    //<<<+++OPENSOURCE_END
    
	/**
	 * @name Measuring operations. All measured in 1/1000 em.
	 */
	/*@{*/

	/**
	 * Get the font's bounding box.
	 *
	 * @param[out] rect			It receives the bounding box of the font. 
	 */
	void					GetFontBBox(FX_RECT& rect) const { rect = m_FontBBox; }
	/** Get the typographic ascent. */
	int						GetTypeAscent() const { return m_Ascent; }
	/** Get the typographic descent, most negative. */
	int						GetTypeDescent() const { return m_Descent; }
	/** Get the angle, expressed in degrees counterclockwise from the vertical, of the dominant vertical strokes of the font. */
	int						GetItalicAngle() const { return m_ItalicAngle; }
	/** Get StemV */
	int						GetStemV() const { return m_StemV; }

	/**
	 * Get a string's width.
	 *
	 * @param[in] pString		Input a string buffer. Must be in font encoding.
	 * @param[in] size			The length in bytes of the string.
	 * @return The width of the string.
	 */
	int						GetStringWidth(const FX_CHAR* pString, int size);
	/**
	 * Get a character's PDF width.
	 *
	 * @param[in] charcode		Input a character code.
	 * @return The PDF width of the character.
	 */
	virtual int				GetCharWidthF(FX_DWORD charcode, int level = 0) = 0;
	/**
	 * Get a character's real width in the font file.
	 *
	 * @param[in] charcode		Input a character code.
	 * @return The real width of the character.
	 */
	virtual int				GetCharTypeWidth(FX_DWORD charcode);
	/**
	 * Get the bounding box of a character.
	 *
	 * @param[in] charcode		Input a character code.
	 * @param[out] rect			It receives the bounding box of the character.
	 * @param[in] level			Recusive level control, optional.
	 */
	virtual void			GetCharBBox(FX_DWORD charcode, FX_RECT& rect, int level = 0) = 0;

	/*@}*/
	
	/** The PDF document. */
	CPDF_Document*			m_pDocument;

	/**
	 * Get a character's path data. for T1, TT, and CIDFont only.
	 *
	 * @param[in] charcode		Input a character code.
	 * @param[in] dest_width	The destination's width.
	 * @return The path data for the character.
	 */
	class CFX_PathData*		LoadGlyphPath(FX_DWORD charcode, int dest_width = 0);

	/** The FXGE font */
	CFX_Font				m_Font;
	//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
	FX_BOOL					Reload();
	//<<<+++OPENSOURCE_END
protected:
	/** Default constructor. */
	CPDF_Font();
	/** Initialzie the font. */
	FX_BOOL					Initialize();
	/** Actually load a font. */
	FX_BOOL					Load();

	/**
	 * Load the font.
	 * Virtual _Load method for derived class to implement.
	 */
	virtual FX_BOOL			_Load() = 0;
	/**
	 * Get the unicode from a character code.
	 * Virtual _UnicodeFromCharCode for derived class to implement.
	 *
	 * @param[in] charcode		Input a charcode.
	 * @return The unicode of the charcode.
	 */
	virtual FX_WCHAR		_UnicodeFromCharCode(FX_DWORD charcode) const = 0;
	/**
	 * Get the character code from a unicode.
	 * Virtual _CharCodeFromUnicode for derived class to implement.
	 *
	 * @param[in] Unicode		Input a unicode.
	 * @return The character code of the unicode.
	 */
	virtual FX_DWORD		_CharCodeFromUnicode(FX_WCHAR Unicode) const = 0;

	/** Load the unicode map. */
	void					LoadUnicodeMap();

	/**
	 * Load a PDF encoding.
	 *
	 * @param[in] pEncoding			The PDF object of the encoding.
	 * @param[out] iBaseEncoding	It receives the zero-base index in the encoding array.
	 * @param[out] pCharNames		It receives the character postscript names for the glyphs.
	 * @param[in] bEmbedded			Whether the font is a embedded font.
	 * @param[in] bTrueType			Whether the font is a truetype font.
	 */
	void					LoadPDFEncoding(CPDF_Object* pEncoding, int& iBaseEncoding, 
								CFX_ByteString*& pCharNames, FX_BOOL bEmbedded, FX_BOOL bTrueType);
	/** Load a font descriptor dictionary. */
	void					LoadFontDescriptor(CPDF_Dictionary*);
	/** Load the character widths. */
	void					LoadCharWidths(FX_WORD* pWidths);
	/** Check the font metrics. */
	void					CheckFontMetrics();

	/** The character map. */
	CFX_CharMap*			m_pCharMap;

	/**
	 * @name Basic font info.
	 */
	/*@{*/

	/** The font type. */
	int						m_FontType;
	/** The base font name. */
	CFX_ByteString			m_BaseFont;

	/** The font stream. */
	CPDF_StreamAcc*			m_pFontFile;
	/** The font dictionary. */
	CPDF_Dictionary*		m_pFontDict;

	/** The to-unicode map. */
	CPDF_ToUnicodeMap*		m_pToUnicodeMap;
	/** Whether the to-unicode map is loaded. */
	FX_BOOL					m_bToUnicodeLoaded;
	FXMT_LOCKOBJECT_DEFINE(m_lockObjFontLoad);
	/*@}*/

	/**
	 * @name Information from font descriptor.
	 */
	/*@{*/

	/** The font flags. */
	int						m_Flags;
	/** The Font bounding box. */
	FX_RECT					m_FontBBox;
	/** The thickness, measured horizontally, of the dominant vertical stems of glyphs in the font. */
	int						m_StemV;
	/** The maximum height above the baseline reached by glyphs in this font, excluding the height of glyphs for accented characters. */
	int						m_Ascent;
	/** The maximum depth below the baseline reached by glyphs in this font. The value is a negative number. */
	int						m_Descent;
	/** The angle, expressed in degrees counterclockwise from the vertical, of the dominant vertical strokes of the font. */
	int						m_ItalicAngle;

	/*@}*/
};

/**
 * @name Predefined encoding.
 */
/*@{*/

/** @brief Built-in encoding. */
#define PDFFONT_ENCODING_BUILTIN		0
/** @brief WinAnsiEncoding. */
#define PDFFONT_ENCODING_WINANSI		1
/** @brief MacRomanEncoding. */
#define PDFFONT_ENCODING_MACROMAN		2
/** @brief MacExpertEncoding. */
#define PDFFONT_ENCODING_MACEXPERT		3
/** @brief StandardEncoding. Adobe standard encoding. */
#define PDFFONT_ENCODING_STANDARD		4
/** @brief Adobe symbol encoding. */
#define PDFFONT_ENCODING_ADOBE_SYMBOL	5
/** @brief ZapfDingbats encoding. */
#define PDFFONT_ENCODING_ZAPFDINGBATS	6
/** @brief PDFDocEncoding. */
#define PDFFONT_ENCODING_PDFDOC			7
/** @brief Microsoft symbol encoding. */
#define PDFFONT_ENCODING_MS_SYMBOL		8
/** @brief Unicode. */
#define PDFFONT_ENCODING_UNICODE		9

/*@}*/

/** @brief Single byte font encoding used by T1 or TT fonts. */
class CPDF_FontEncoding : public CFX_Object
{
public:
	/** Default constructor. */
	CPDF_FontEncoding();
	/**
	 * Construct with a predefined encoding.
	 *
	 * @param[in] PredefinedEncoding		The input predefined encoding.
	 */
	CPDF_FontEncoding(int PredefinedEncoding);

	/**
	 * Load encoding from a PDF encoding object.
	 *
	 * @param[in] pEncoding		The PDF object of encoding.
	 */
	void					LoadEncoding(CPDF_Object* pEncoding);
	/**
	 * Check whether the encoding is identical with another encoding.
	 *
	 * @param[in] pAnother		The another encoding.
	 * @return Non-zero means identical, otherwise not identical. 
	 */
	FX_BOOL					IsIdentical(CPDF_FontEncoding* pAnother) const;

	/**
	 * Get the unicode from a charcode.
	 *
	 * @param[in] charcode		The input charcode.
	 * @return The unicode of the charcode.
	 */
	FX_WCHAR				UnicodeFromCharCode(FX_BYTE charcode) const { return m_Unicodes[charcode]; }
	/**
	 * Get the charcode from a unicode.
	 *
	 * @param[in] unicode		The input unicode.
	 * @return The charcode of the unicode. -1 for not found.
	 */
	int						CharCodeFromUnicode(FX_WCHAR unicode) const;

	/**
	 * Set the unicode of a charcode.
	 *
	 * @param[in] charcode		Input a charcode.
	 * @param[in] unicode		The new unicode value for the charcode.
	 */
	void					SetUnicode(FX_BYTE charcode, FX_WCHAR unicode) { m_Unicodes[charcode] = unicode; }

	/**
	 * Realize the font encoding in a PDF encoding object. Can be NULL is not needed.
	 * @return A new PDF encoding object corresponding to the encoding table.
	 */
	CPDF_Object*			Realize();

public:
	/** The encoding table. */
	FX_WCHAR				m_Unicodes[256];
};

/** @brief Common structures for Type1 and TrueType fonts. */
class CPDF_SimpleFont : public CPDF_Font
{
public:
	/** Default constructor. */
	CPDF_SimpleFont();
	/** The destructor. */
	virtual ~CPDF_SimpleFont();

	/** Get the font encoding. */
	CPDF_FontEncoding*		GetEncoding() { return &m_Encoding; }

	virtual int				GetCharWidthF(FX_DWORD charcode, int level = 0);
	virtual void			GetCharBBox(FX_DWORD charcode, FX_RECT& rect, int level = 0);
	virtual int				GlyphFromCharCode(FX_DWORD charcode, FX_BOOL *pVertGlyph = NULL);

	virtual FX_BOOL			IsUnicodeCompatible() const;
protected:
	/** Load common parameters. */
	FX_BOOL					LoadCommon();
	/** Load substitute font. */
	void					LoadSubstFont();
	/** Load face metrics. */
	void					LoadFaceMetrics();

	/** Load the glyph map. */
	virtual void			LoadGlyphMap() = 0;
	virtual FX_WCHAR		_UnicodeFromCharCode(FX_DWORD charcode) const { return m_Encoding.UnicodeFromCharCode((FX_BYTE)charcode); }
	virtual FX_DWORD		_CharCodeFromUnicode(FX_WCHAR Unicode) const { return m_Encoding.CharCodeFromUnicode(Unicode); }

	/**
	 * @name Font encoding information.
	 */
	/*@{*/

	/** The font character encoding. */
	CPDF_FontEncoding		m_Encoding;
	/** Glyph index for embedded or substituted font. 0xffff for not found. */
	FX_WORD					m_GlyphIndex[256];
	FX_WORD					m_ExtGID[256];
	/*@}*/

	/**
	 * @name PDF encoding information.
	 */
	/*@{*/

	/** Character names array. 256 strings or NULL. */
	CFX_ByteString*			m_pCharNames;
	/** The base encoding. */
	int						m_BaseEncoding;

	/*@}*/

	/**
	 * @name Metrics information.
	 */
	/*@{*/

	/** Width (horizontal advance) array. In 1/1000 em. */
	FX_WORD					m_CharWidth[256];
	/** Character bounding boxes. */
	FX_SMALL_RECT			m_CharBBox[256];
	/** Whether to use the font's default width. */
	FX_BOOL					m_bUseFontWidth;
	/**
	 * Load the metrics of a character.
	 *
	 * @param[in] charcode		Input a character code. 
	 */
	void					LoadCharMetrics(int charcode);

	/*@}*/
};

/** @brief PDF type1 font. */
class CPDF_Type1Font : public CPDF_SimpleFont
{
public:
	/** Default constructor. */
	CPDF_Type1Font();

	/** Get an ID of standard 14 font. -1 for none. See list of standard fonts in PDF Reference. */
	int						GetBase14Font() { return m_Base14Font; }
	virtual int				GlyphFromCharCodeExt(FX_DWORD charcode);

protected:
	virtual FX_BOOL			_Load();
	/** Whether the font is a base-14 font. */
	int						m_Base14Font;

	virtual void			LoadGlyphMap();
};

/** @brief PDF truetype font. */
class CPDF_TrueTypeFont : public CPDF_SimpleFont
{
public:
	/** Default constructor. */
	CPDF_TrueTypeFont();

protected:
	virtual FX_BOOL			_Load();
	virtual void			LoadGlyphMap();
};

/** @brief Type3 character information. */
#ifdef _FXM_OPENSOURCE_
class CPDF_Type3Char : public CFX_Object
#else
//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
class CPDF_Type3Char : public CFX_LockObject
//<<<+++OPENSOURCE_END
#endif
{
public:
	/** Default constructor. */
	CPDF_Type3Char();
	/** The destructor. */
	~CPDF_Type3Char();

	/** Load type3 image glyph.*/
	FX_BOOL LoadBitmap(CPDF_RenderContext* pContext);

	/** Whether the type3 character is colored. */
	FX_BOOL					m_bColored;
	/** Whether using a page resource therefore we can't load the char. */
	FX_BOOL					m_bPageRequired;

	/**
	 * @name The character can be either a full form, or an image object as a shortcut (which is used by raster fonts).
	 */
	/*@{*/

	/** The form pointer if it's a form. */
	CPDF_Form*				m_pForm;

	/** The image matrix if it's a image. */
	CFX_AffineMatrix		m_ImageMatrix;
	/** The image pointer if it's a image. */
	CFX_DIBitmap*			m_pBitmap;

	/*@}*/

	/** The character width. in font coordinate (1/1000 of em). */
	int						m_Width;
	/** The character's bounding box. in font coordinate (1/1000 of em). */
	FX_RECT					m_BBox;
};

class CPDF_Type3Font : public CPDF_SimpleFont
{
public:
	CPDF_Type3Font();
	virtual ~CPDF_Type3Font();

	void					SetPageResources(CPDF_Dictionary* pResources) { m_pPageResources = pResources; }

	CPDF_Type3Char*			LoadChar(FX_DWORD charcode, int level = 0);
	virtual int				GetCharWidthF(FX_DWORD charcode, int level = 0);
	virtual int				GetCharTypeWidth(FX_DWORD charcode) { return GetCharWidthF(charcode); }
	virtual void			GetCharBBox(FX_DWORD charcode, FX_RECT& rect, int level = 0);
	CFX_AffineMatrix&		GetFontMatrix() { return m_FontMatrix; }

	void					CheckType3FontMetrics();

private:
	virtual FX_BOOL			_Load();
	virtual void			LoadGlyphMap() {}

	int						m_CharWidthL[256];	// In 1/1000 font unit
	CPDF_Dictionary*		m_pCharProcs;
	CPDF_Dictionary*		m_pPageResources;
	CPDF_Dictionary*		m_pFontResources;	// Resources provided with this font
	CFX_MapPtrToPtr			m_CacheMap;		// Map charcode to CPDF_Type3Char*
	CFX_MapPtrToPtr			m_DeletedMap;

protected:
	CFX_AffineMatrix		m_FontMatrix;
};

/**
 * @name CID Font charsets (also called collections).
 */
/*@{*/

/** @brief Unknown. */ 
#define CIDSET_UNKNOWN		0
/** @brief Adobe-GB1. */
#define CIDSET_GB1			1
/** @brief Adobe-CNS1. */
#define CIDSET_CNS1			2
/** @brief Adobe-Japan1. */
#define CIDSET_JAPAN1		3
/** @brief Adobe-Korea1. */
#define CIDSET_KOREA1		4
/** @brief Unicode. */
#define CIDSET_UNICODE		5

/*@}*/

/** @brief CID specific font data. */
class CPDF_CIDFont : public CPDF_Font
{
public:
	/** Default constructor. */
	CPDF_CIDFont();
	/** The destructor. */
	virtual ~CPDF_CIDFont();

	/** Load GB2312 charset. */
	FX_BOOL					LoadGB2312();

	virtual int				GlyphFromCharCode(FX_DWORD charcode, FX_BOOL *pVertGlyph = NULL);
	virtual int				GetCharWidthF(FX_DWORD charcode, int level = 0);
	virtual void			GetCharBBox(FX_DWORD charcode, FX_RECT& rect, int level = 0);

	/**
	 * Get the CID from charcode.
	 *
	 * @param[in] charcode		Input a charcode.
	 * @return The CID of the charcode.
	 */
	FX_WORD					CIDFromCharCode(FX_DWORD charcode) const;

	/** Whether the font is a truetype font. */
	FX_BOOL					IsTrueType() { return !m_bType1; }

	/**
	 * @name String operations. Note font may use multibyte encoding.
	 */
	/*@{*/

	virtual FX_DWORD		GetNextChar(const FX_CHAR* pString, int& offset) const;
	virtual int				CountChar(const FX_CHAR* pString, int size) const;
	virtual int				AppendChar(FX_LPSTR str, FX_DWORD charcode) const;
	virtual int				GetCharSize(FX_DWORD charcode) const;

	/*@}*/

	/** Get the character set. */
	int						GetCharset() const { return m_Charset; }
	/** Get the CID transform. */
	FX_LPCBYTE				GetCIDTransform(FX_WORD CID) const;

	/**
	 * @name Vertical writing.
	 */
	/*@{*/

	/** Check whether the font is vertical writing. */
	virtual FX_BOOL			IsVertWriting() const;

	/**
	 * Get glyph width in vertical writing.
	 *
	 * @param[in] CID		Input a CID.
	 */
	short					GetVertWidth(FX_WORD CID) const;
	/**
	 * Get character origin in vertical writing.
	 *
	 * @param[in] CID			Input a CID.
	 * @param[out] vx			It receives the x-coordinate of the character origin.
	 * @param[out] vy			It receives the y-coordinate of the character origin.
	 */
	void					GetVertOrigin(FX_WORD CID, short& vx, short& vy) const;

	/*@}*/

	virtual FX_BOOL			IsUnicodeCompatible() const;
	virtual FX_BOOL			IsFontStyleFromCharCode(FX_DWORD charcode) const;

protected:
	friend class			CPDF_Font;

	virtual FX_BOOL			_Load();
	virtual FX_WCHAR		_UnicodeFromCharCode(FX_DWORD charcode) const;
	virtual FX_DWORD		_CharCodeFromUnicode(FX_WCHAR Unicode) const;
			int				GetGlyphIndex(FX_DWORD unicodeb, FX_BOOL *pVertGlyph);

	/** mapping from charcode to CID. */
	CPDF_CMap*				m_pCMap;
	/** mapping, if we have allocated one privately */
	CPDF_CMap*				m_pAllocatedCMap;
	/** mapping from CID to unicode. */
	CPDF_CID2UnicodeMap*	m_pCID2UnicodeMap;

	/** Character set information. */
	int						m_Charset;

	/** Type1 or TrueType. */
	FX_BOOL					m_bType1;
	/** CIDToGIDMap. */
	CPDF_StreamAcc*			m_pCIDToGIDMap;
	FX_BOOL					m_bCIDIsGID;

	/**
	 * @name Metrics information.
	 */
	/*@{*/

	/** Default char width. */
	FX_WORD					m_DefaultWidth;
	/** Char widths for ANSI part of the font. */
	FX_WORD*				m_pAnsiWidths;
	/** We cache for the first 256 codes. */
	FX_SMALL_RECT			m_CharBBox[256];
	/** Groups of three numbers: first, last, width. */
	CFX_DWordArray			m_WidthList;
	/** Default Y offset of the vertical origin (from the horizontal origin). */
	short					m_DefaultVY;
	/** Default vertical origin offset for next character. */
	short					m_DefaultW1;
	/** Groups of five numbers: first, last, width1, vx, vy. */
	CFX_DWordArray			m_VertMetrics;

	/*@}*/

	/** Load a metrics array. */
	void					LoadMetricsArray(CPDF_Array* pArray, CFX_DWordArray& result, int nElements);
	/** Load the substitute font. */
	void					LoadSubstFont();
	/** The base name is CourierStd, CourierStd-Bold, CourierStd-BoldOblique or CourierStd-Oblique. */
	FX_BOOL					m_bAdobeCourierStd;
	/** Process the gsub table of the trutype font.*/
	CFX_CTTGSUBTable*			m_pTTGSUBTable;

};
//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
/** @brief An utility class for CID processing. */
class CPDF_CIDUtil
{
public:
	/** Whether the specified CID is vertical Japanese CID. */
	static FX_BOOL			IsVerticalJapanCID(FX_WORD CID);
};
//<<<+++OPENSOURCE_END
/**
 * @name Color space families.
 */
/*@{*/

/** @brief DeviceGray. */
#define PDFCS_DEVICEGRAY		1
/** @brief DeviceRGB. */	
#define PDFCS_DEVICERGB			2
/** @brief DeviceCMYK. */
#define PDFCS_DEVICECMYK		3
/** @brief CalGray. */
#define PDFCS_CALGRAY			4
/** @brief CalRGB. */
#define PDFCS_CALRGB			5
/** @brief Lab. */
#define PDFCS_LAB				6
/** @brief ICCBased. */
#define PDFCS_ICCBASED			7
/** @brief Separation. */
#define PDFCS_SEPARATION		8
/** @brief DeviceN. */
#define PDFCS_DEVICEN			9
/** @brief Indexed. */
#define PDFCS_INDEXED			10
/** @brief Pattern. */
#define PDFCS_PATTERN			11

/*@}*/

/** @brief PDF color space class. */
#ifdef _FXM_OPENSOURCE_
class CPDF_ColorSpace : public CFX_Object
#else
//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
class CPDF_ColorSpace : public CFX_LockObject
//<<<+++OPENSOURCE_END
#endif
{
public:
	/**
	 * Get stocked color spaces. Stocked color spaces can not be destroyed.
	 * The following color spaces are stocked:\n
	 * /DeviceGray, /DeviceRGB, /DeviceCMYK, /Pattern (colored patterns only).
	 *
	 * @param[in] Family			The color space family.
	 * @return A color space.
	 */
	static CPDF_ColorSpace* GetStockCS(int Family);

	/**
	 * Load color space from a PDF object.
	 * The object can be a name or an array.
	 * The returned color space can be one of the stocked color spaces, or a new instance of
	 * one derived color space class. Application should call Release() to destroy the new
	 * instance when it's not used any more.
	 *
	 * @param[in] pDoc				The PDF document.
	 * @param[in] pCSObj			The PDF object of a color space.
	 * @return A color space.
	 */
	static CPDF_ColorSpace*	Load(CPDF_Document* pDoc, CPDF_Object* pCSObj);

	/**
	 * Applications should not delete color space directly, because some color spaces are
	 * stocked. Call Release() function instead.
	 */
	void					ReleaseCS();

	/** Get color buffer size. */
	int						GetBufSize() const;
	/** Create a color buffer. */
	FX_FLOAT*			CreateBuf();
	/**
	 * Get the default color.
	 *
	 * @param[out] buf				It receives the color components.
	 */
	void					GetDefaultColor(FX_FLOAT* buf) const;

	/** Get the number of components. */
	int						CountComponents() const { return m_nComponents; }
	/** Get the color space family. */
	int						GetFamily() const { return m_Family; }
	/**
	 * Get the default value of a component.
	 *
	 * @param[in] iComponent		The zero-based component index.
	 * @param[out] value			It receives the component value.
	 * @param[out] min				It receives the minimize component value valid.
	 * @param[out] max				It receives the maximize component value valid.
	 */
	virtual void			GetDefaultValue(int iComponent, FX_FLOAT& value, FX_FLOAT& min, FX_FLOAT& max) const
							{ value = 0; min = 0; max = 1.0f; }

	/** Check whether it's sRGB or equivalent color space. */
	FX_BOOL					sRGB() const;

	/**
	 * @name Convert with default RGB color space.
	 */
	/*@{*/

	/**
	 * Convert a color to RGB color space.
	 *
	 * @param[in] pBuf				The input color components.
	 * @param[out] R				It receives the red component.
	 * @param[out] G				It receives the green component.
	 * @param[out] B				It receives the blue component.
	 * @return Non-zero means success, otherwise failure.
	 */
	virtual FX_BOOL			GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const = 0;
	/**
	 * Convert a color from RGB color space.
	 *
	 * @param[out] pBuf				It receives the converted color.
	 * @param[in] R					The red component of the color.
	 * @param[in] G					The green component of the color.
	 * @param[in] B					The blue component of the color.
	 * @return Non-zero means success, otherwise failure.
	 */
	virtual FX_BOOL			SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const { return FALSE; }

	/*@}*/

	/**
	 * @name Convert with default CMYK color space.
	 */
	/*@{*/

	/**
	 * Convert a color to CMYK color space.
	 *
	 * @param[in] pBuf				The input color components.
	 * @param[out] c				It receives the C component.
	 * @param[out] m				It receives the M component.
	 * @param[out] y				It receives the Y component.
	 * @param[out] k				It receives the K component.
	 * @return Non-zero means success, otherwise failure.
	 */
	FX_BOOL					GetCMYK(FX_FLOAT* pBuf, FX_FLOAT& c, FX_FLOAT& m, FX_FLOAT& y, FX_FLOAT& k) const;
	/**
	 * Convert a color from CMYK color space.
	 *
	 * @param[out] pBuf				It receives the converted color.
	 * @param[in] c					The C component of the color.
	 * @param[in] m					The M component of the color.
	 * @param[in] y					The Y component of the color.
	 * @param[in] k					The K component of the color.
	 * @return Non-zero means success, otherwise failure.
	 */
	FX_BOOL					SetCMYK(FX_FLOAT* pBuf, FX_FLOAT c, FX_FLOAT m, FX_FLOAT y, FX_FLOAT k) const;

	/*@}*/

	/**
	 * Convert a bitmap scan line. Source must be 8bpc with default encoding, dest is be 24bpp sRGB.
	 *
	 * @param[in] dest_buf			The destinate line buffer.
	 * @param[in] src_buf			The source line buffer.
	 * @param[in] pixels			The pixel in the line.
	 * @param[in] image_width		The image_width.
	 * @param[in] image_height		The image height.
	 * @param[in] bTransMask		Whether translate color for mask.
	 */
	virtual void			TranslateImageLine(FX_LPBYTE dest_buf, FX_LPCBYTE src_buf, int pixels,
								int image_width, int image_height, FX_BOOL bTransMask = FALSE) const;

	/** Get the color space parameters array. */
	CPDF_Array*&			GetArray() { return m_pArray; }

	/** Get the max index. for Indexed color space only. */
	int						GetMaxIndex() const;
	/** Get based color space. */
	virtual CPDF_ColorSpace*	GetBaseCS() const { return NULL; }

	/** Enable or disable standard conversion. */
	virtual void			EnableStdConversion(FX_BOOL bEnabled);

	CPDF_Document*			m_pDocument;
protected:
	/** Default constructor. */
	CPDF_ColorSpace();
	/** The destructor. */
	virtual ~CPDF_ColorSpace() {}

	virtual FX_BOOL			v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) { return TRUE; }
	virtual FX_BOOL			v_GetCMYK(FX_FLOAT* pBuf, FX_FLOAT& c, FX_FLOAT& m, FX_FLOAT& y, FX_FLOAT& k) const { return FALSE; }
	virtual FX_BOOL			v_SetCMYK(FX_FLOAT* pBuf, FX_FLOAT c, FX_FLOAT m, FX_FLOAT y, FX_FLOAT k) const { return FALSE; }

	/** The color space family. */
	int						m_Family;
	/** The number of components. */
	int						m_nComponents;
	/** The color space parameters. NULL for simple CS (single name without parameters). */
	CPDF_Array*				m_pArray;
	/** Indicates use standard conversion. */
	FX_DWORD				m_dwStdConversion;
};

/** @brief PDF color class. */
class CPDF_Color : public CFX_Object
{
public:
	/** Construct an empty color. */
	CPDF_Color() { m_pBuffer = NULL; m_pCS = NULL; }
	/**
	 * Construct with a color space family.
	 *
	 * @param[in] family			The input color space family.
	 */
	CPDF_Color(int family);
	/** The destructor. */
	~CPDF_Color();

	/** Check whether the color is null. */
	FX_BOOL					IsNull() const { return m_pBuffer == NULL; }

	/**
	 * Compare with another color.
	 *
	 * @param[in] other				The another color.
	 * @return Non-zero means equal, otherwise not equal.
	 */
	FX_BOOL					IsEqual(const CPDF_Color& other) const;
	/** Check whether the color is a pattern. */
	FX_BOOL					IsPattern() const { return m_pCS && m_pCS->GetFamily() == PDFCS_PATTERN; }

	/**
	 * Copy from another color.
	 *
	 * @param[in] pSrc				The source color.
	 */
	void					Copy(const CPDF_Color* pSrc);
	/**
	 * Set the color space.
	 *
	 * @param[in] pCS				The new color space.
	 */
	void					SetColorSpace(CPDF_ColorSpace* pCS);

	/**
	 * Set color components in normal color space.
	 *
	 * @param[in] comp				The input color components.
	 */
	void					SetValue(FX_FLOAT* comp);
	/**
	 * Set a color in pattern color space.
	 *
	 * @param[in] pPattern			The input pattern.
	 * @param[in] comp				The components.
	 * @param[in] ncomps			The count of components.
	 */
	void					SetValue(CPDF_Pattern* pPattern, FX_FLOAT* comp, int ncomps);

	/**
	 * Convert to default RGB color space, using single byte encoding (0-255).
	 *
	 * @param[out] R				It receives the red component.
	 * @param[out] G				It receives the green component.
	 * @param[out] B				It receives the blue component.
	 * @return If the return value is FALSE, then this color should be treated as "no-color".
	 */
	FX_BOOL					GetRGB(int& R, int& G, int& B) const;

	/**
	 * Get pattern information for #PDFCS_PATTERN color space.
	 *
	 * @return Pointer to pattern object. NULL if this color is not a pattern.
	 */
	CPDF_Pattern*			GetPattern() const;

	/**
	 * Get base color space for an uncolored tiling pattern.
	 *
	 * @return Pointer to color space. NULL if not applicable.
	 */
	CPDF_ColorSpace*		GetPatternCS() const;

	/*
	 * Get component buffer for the base color space used for pattern (uncolored tiling only).
	 *
	 * @return A buffer for the components. NULL if not applicable.
	 */
	FX_FLOAT*			GetPatternColor() const;

	/** The color space. NULL for unspecified color space. */
	CPDF_ColorSpace*		m_pCS;
	/** The components. NULL for unspecified color. */
	FX_FLOAT*			m_pBuffer;

protected:
	void	ReleaseBuffer();
	void	ReleaseColorSpace();
};

/**
 * @name Pattern types.
 */
/*@{*/

/** @brief repeating pattern cells. */
#define PATTERN_TILING		1
/** @brief gradient color shading. */
#define PATTERN_SHADING		2

/*@}*/

/** @brief PDF pattern class. */
class CPDF_Pattern : public CFX_Object
{
public:
	/** The destructor. */
	virtual ~CPDF_Pattern() {}

	/** Dictionary for shading, stream for tiling. */
	CPDF_Object*			m_pPatternObj;

	/** The pattern type. */
	int						m_PatternType;
	/** matrix from pattern to parent stream. */
	CFX_AffineMatrix		m_Pattern2Form;
	CFX_AffineMatrix		m_ParentMatrix;
	/** The PDF document. */
	CPDF_Document*			m_pDocument;
	
	FXMT_LOCKOBJECT_DEFINE(m_lockObjLoad);
protected:
	/** Default constructor. can't construct a CPDF_Pattern directly. */
	CPDF_Pattern(const CFX_AffineMatrix* pParentMatrix) { if (pParentMatrix) m_ParentMatrix = *pParentMatrix;}
};

/** @brief PDF tiling pattern class. */
class CPDF_TilingPattern : public CPDF_Pattern
{
public:
	/**
	 * Construct with a pattern stream.
	 *
	 * @param[in] pDoc				The PDF document.
	 * @param[in] pPatternObj		The PDF object of the pattern.
	 */
	CPDF_TilingPattern(CPDF_Document* pDoc, CPDF_Object* pPatternObj, const CFX_AffineMatrix* parentMatrix);
	/** The destructor. */
	virtual ~CPDF_TilingPattern();

	/** load all following data. */
	FX_BOOL				Load();

	/**
	 * @name properties specific for tiling pattern.
	 */
	/*@{*/

	/** Whether the pattern is a colored pattern or not. */
	FX_BOOL				m_bColored;
	/** The bounding box. In pattern space. */
	CFX_FloatRect		m_BBox;
	/** The desired horizontal spacing between pattern cells. In pattern space, absolute values only. */
	FX_FLOAT			m_XStep;
	/** The desired vertical spacing between pattern cells. In pattern space, absolute values only. */
	FX_FLOAT			m_YStep;
	
	/*@}*/

	/** All objects contained in this pattern. NULL if not loaded. */
	CPDF_Form*			m_pForm;
};

/** @brief PDF shading pattern class. */
class CPDF_ShadingPattern : public CPDF_Pattern
{
public:
	/**
	 * Construct with a PDF object of pattern.
	 *
	 * @param[in] pDoc			The PDF document.
	 * @param[in] pPatternObj	The PDF object of pattern.
	 * @param[in] bShading		Whether it's just a shading object.
	 */
	CPDF_ShadingPattern(CPDF_Document* pDoc, CPDF_Object* pPatternObj, FX_BOOL bShading, const CFX_AffineMatrix* parentMatrix);
	/** The destructor. */
	virtual ~CPDF_ShadingPattern();

	/** The PDF object of shading. */
	CPDF_Object*		m_pShadingObj;
	/** Whether it's just a shading object. */
	FX_BOOL				m_bShadingObj;

	/** load all following data. */
	FX_BOOL				Load();

	/** reload shading data after shading dictionary changed */
	FX_BOOL				Reload();

	/** The shading type. 0 for not loaded. */
	int					m_ShadingType;
	/** The color space. */
	CPDF_ColorSpace*	m_pCS;
	
	//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
#ifdef _FPDFAPI_CACHEPOINTER_
	CPDF_ColorSpace**	m_pPtrCS;
#endif
	//<<<+++OPENSOURCE_END
	/** The function array. */
	CPDF_Function*		m_pFunctions[4];
	/** The count of functions. */
	int					m_nFuncs;

protected:
	void	Clear();
};

/** @brief PDF mesh vertex's coords and color value. */
struct CPDF_MeshVertex
{
	FX_FLOAT x, y;
	FX_FLOAT r, g, b;
};

/** @brief PDF mesh stream class. */
class CPDF_MeshStream : public CFX_Object
{
public:
	/**
	 * Loading the shading stream, functions, and colorspaces.
	 *
	 * @param[in] pShadingStream	The input shading stream.
	 * @param[in] pFuncs			The array of 1-in, 1-out functions for shading.
	 * @param[in] nFuncs			The count of functions.
	 * @param[in] pCS				The base colorspace for shading.
	 * @return TRUE for success, FALSE for failure.
	 */
	FX_BOOL				Load(CPDF_Stream* pShadingStream, CPDF_Function** pFuncs, int nFuncs, CPDF_ColorSpace* pCS);
	/** Read a vertex flag from mesh stream. */
	FX_DWORD			GetFlag();
	/** Read a vertex coords from mesh stream. */
	void				GetCoords(FX_FLOAT& x, FX_FLOAT& y);
	/** Read a vertex color from mesh stream. */
	void				GetColor(FX_FLOAT& r, FX_FLOAT& g, FX_FLOAT& b);
	/** Read a vertex from mesh stream. */
	FX_DWORD 			GetVertex(CPDF_MeshVertex& vertex, CFX_AffineMatrix* pObject2Bitmap);
	/** Read a vertex array from mesh stream. */
	FX_BOOL				GetVertexRow(CPDF_MeshVertex* vertex, int count, CFX_AffineMatrix* pObject2Bitmap);

	CPDF_Function**	m_pFuncs;
	CPDF_ColorSpace*	m_pCS;
	FX_DWORD			m_nFuncs, m_nCoordBits, m_nCompBits, m_nFlagBits, m_nComps;
	FX_DWORD			m_CoordMax, m_CompMax;
	FX_FLOAT			m_xmin, m_xmax, m_ymin, m_ymax;
	FX_FLOAT			m_ColorMin[8], m_ColorMax[8];
	CPDF_StreamAcc		m_Stream;
	CFX_BitStream		m_BitStream;
};

/**
 * @name Image compress types.
 */
/*@{*/

/** @brief no compress. */
#define PDF_IMAGE_NO_COMPRESS				0x0000
/** @brief lossy compress. */
#define PDF_IMAGE_LOSSY_COMPRESS			0x0001
/** @brief lossless compress. */
#define PDF_IMAGE_LOSSLESS_COMPRESS			0x0002
/** @brief mask image lossy compress. */
#define PDF_IMAGE_MASK_LOSSY_COMPRESS		0x0004
/** @brief mask image lossless compress. */
#define PDF_IMAGE_MASK_LOSSLESS_COMPRESS	0x0008

/*@}*/
class CPDF_ImageSetParam
{
public:
	CPDF_ImageSetParam()
		: pMatteColor(NULL)
		, nQuality(80)
	{

	}
	FX_ARGB* pMatteColor;
	FX_INT32 nQuality;
};

/** @brief Image data holding class. It can be an XObject image, or an inline image. */
class CPDF_Image : public CFX_Object
{
public:
	/**
	 * Construct an empty image.
	 *
	 * @param[in] pDoc			The PDF document.
	 */
	CPDF_Image(CPDF_Document* pDoc);
	/** The destructor. */
	~CPDF_Image();

	/**
	 * Load from an image stream.
	 *
	 * @param[in] pImageStream			The input image stream.
	 * @param[in] bInline				Whether this is an inline image. If yes, the stream will be destroyed when image destroyed
	 * @return Non-zero means success, otherwise failure.
	 */
	FX_BOOL					LoadImageF(CPDF_Stream* pImageStream, FX_BOOL bInline);
	/** Release the image. */
	void					Release();
	/** Clone an image. */
	CPDF_Image*				Clone();
	/** Whether the image is inline.*/
	FX_BOOL					IsInline() {return m_bInline;}
	/** Set the inline image dictionary.*/
	void					SetInlineDict(CPDF_Dictionary* pDict) {m_pInlineDict = pDict;}
	/** Get the inline image dictionary.*/
	CPDF_Dictionary*		GetInlineDict() const {return m_pInlineDict;}

	/** Get the image stream. */
	CPDF_Stream*			GetStream() const { return m_pStream; }
	/** Get the image dictionary. */
#ifndef _FXM_OPENSOURCE_
	//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
	CPDF_Dictionary*		GetDict() const { return m_pStream->GetDict(); }
	//<<<+++OPENSOURCE_END
#else
	//<<<+++OPENSOURCE_BEGIN LIC==GOOGLE
	CPDF_Dictionary*		GetDict() const { return m_pStream ? m_pStream->GetDict() : NULL; }
	//<<<+++OPENSOURCE_END
#endif
	/** Get the optional content dictionary. */
	CPDF_Dictionary*		GetOC() const { return m_pOC; }
	/** Get the document. */
	CPDF_Document*			GetDocument() const { return m_pDocument; }

	/**
	 * @name Get original pixel size.
	 */
	/*@{*/

	/** Get the pixel height. */
	FX_INT32				GetPixelHeight() const { return m_Height; }
	/** Get the pixel width. */
	FX_INT32				GetPixelWidth() const { return m_Width; }

	/*@}*/

	/** Check whether the image is a mask. */
	FX_BOOL					IsMask() const { return m_bIsMask; }
	/** Check whether image interpolation is to be performed. */
	FX_BOOL					IsInterpol() const { return m_bInterpolate; }

	/**
	 * Load DIB source of the image. Optionally the mask info can be returned as well
	 * NOTE: the result bitmaps are NOT cached, so the caller must release them when finished using.
	 *
	 * @param[out] ppMask			It receives the mask of the image.
	 * @param[out] pMatteColor		It receives the matte color. 
	 * @param[in] bStdCS			Indicates whether use standard colorspace conversion(CMYK->RGB) or not.
	 * @param[in] GroupFamily		The group color space family for whether to adopt a special algorithm,
									and the group is a group or form include this image source.
	 * @param[in] bLoadMask			when processing luminosity to mask alpha, adopt a special algorithm.
	 * @return The DIB source constructed.
	 */
	CFX_DIBSource*			LoadDIBSource(CFX_DIBSource** ppMask = NULL, FX_DWORD* pMatteColor = NULL, FX_BOOL bStdCS = FALSE, FX_DWORD GroupFamily = 0, FX_BOOL bLoadMask = FALSE) const;

	/**
	 * @name Functions implemented in EDIT module.
	 */
	/*@{*/

	/**
	 * Change image data from a DIB. Note the bitmaps stored in the page cache must be reset 
	 * by ResetCache() for all loaded pages.
	 * Note: 8bpp image doesn't use JBIG2 compress.
	 *
	 * @param[in] pDIBitmap			The DIB data.
	 * @param[in] iCompress			Compress type.
	 * @param[in] pFileWrite		A file writing object is used to store DIB data, if available.
	 * @param[in] pFileRead			A file reading object is used to initialize image stream, if available.
	 * @param[in] pMask				Mask image, it's valid only <i>pDIBitmap</i> has on alpha channel. Mask image should be FXDIB_1bppMask or FXDIB_8bppMask.
	 * @param[in] pMatteColor		Matte color indicate image has been preblended. Only for FXDIB_Argb format.
	 * @remark	pFileWrite and pFileRead should be valid together if caller need save memory.
	 */
	void					SetImage(const CFX_DIBitmap* pDIBitmap, FX_INT32 iCompress, IFX_FileWrite *pFileWrite = NULL, IFX_FileRead *pFileRead = NULL, const CFX_DIBitmap* pMask = NULL, const CPDF_ImageSetParam* pParam = NULL);
    
	/**
	 * Change image data from a JPEG encoded block. Note the bitmaps stored in the 
	 * page cache must be dropped by ResetCache() for all loaded pages.
	 *
	 * @param[in] pImageData		The JPEG data.
	 * @param[in] size				The size in bytes of the JPEG data.
	 */
	void					SetJpegImage(FX_BYTE* pImageData, FX_DWORD size);
	/**
	 * Change image data from a JPEG stream. Note the bitmaps stored in the 
	 * page cache must be dropped by ResetCache() for all loaded pages.
	 *
	 * @param[in] pFile		JPEG data stream.
	 */
	void					SetJpegImage(IFX_FileRead *pFile);
    
	/**
	 * Reset the page cache.
	 *
	 * @param[in] pPage				The page.
	 * @param[in] pDIBitmap			The new DIB to set.
	 */
	void					ResetCache(CPDF_Page* pPage, const CFX_DIBitmap* pDIBitmap);

	/*@}*/
public:
	// For progressive processing.
	FX_BOOL					StartLoadDIBSource(CPDF_Dictionary* pFormResource, CPDF_Dictionary* pPageResource, FX_BOOL bStdCS = FALSE, FX_DWORD GroupFamily = 0, FX_BOOL bLoadMask = FALSE);
	FX_BOOL					Continue(IFX_Pause* pPause);
	CFX_DIBSource*			DetachBitmap();
	CFX_DIBSource*			DetachMask();
	CFX_DIBSource*			m_pDIBSource;
	CFX_DIBSource*			m_pMask;
	FX_DWORD				m_MatteColor;
private:
	/** The image stream. */
	CPDF_Stream*			m_pStream;
	FX_BOOL					m_bInline;
	CPDF_Dictionary*		m_pInlineDict;

	/** The pixel height. */
	FX_INT32				m_Height;
	/** The pixel width. */
	FX_INT32				m_Width;
	/** Whether the image is a mask. */
	FX_BOOL					m_bIsMask;
	/** Whether image interpolation is to be performed. */
	FX_BOOL					m_bInterpolate;
	/** The PDF document. */
	CPDF_Document*			m_pDocument;
	/** optional content: cached here for better performance. */
	CPDF_Dictionary*		m_pOC;

	FXMT_LOCKOBJECT_DEFINE(m_lockObjImage);

	CPDF_Dictionary*	InitJPEG(FX_LPBYTE pData, FX_DWORD size);
#ifndef _FXM_OPENSOURCE_
	//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
	friend class CPDF_PageObjectsCache;
	//<<<+++OPENSOURCE_END
#endif
};

//<<<+++OPENSOURCE_MUST_BEGIN
#endif // _FPDF_RESOURCE_
//<<<+++OPENSOURCE_MUST_END

/** @} */


